import random
import string

from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from django.views import View
from rest_framework.response import Response
from rest_framework.views import APIView

from z_Userapp.MyPlant import SimpleFactory
from z_Userapp.MyRedis import MyRedis
from z_Userapp.MyRedisQueue import RedisQueue
from z_Userapp.MyThread import dojob, MessageModel
from z_Userapp.models import *
import redis
from z_Userapp.sers import UserSer, UserSer1, WorkOrderSer, ChatSer
from z_Userapp.test_celery_updateuser import detail_updateuser
import asyncio

r = redis.Redis(decode_responses=True)


# 注册
class Register(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        try:
            user = UserModel(username=username, password=password)
            user.save()
            return Response({'code': 200, 'msg': '恭喜您，注册成功'})
        except Exception as e:
            print(str(e))
            return Response({'code': 405, 'msg': 'Sorry，用户已存在'})


# 登录
class Login(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        r = redis.Redis()
        if r.get(username + "black"):
            return Response({'msg': 'Sorry，您的账户已经被锁定了，30分钟之后重试', 'code': 400})
        user = UserModel.objects.filter(username=username, password=password).first()
        if user:
            return Response({'msg': '登录成功', 'code': 200, 'id': user.id, 'user_level': user.user_level})

        # 判断是否存在该键值对,如果不存在,则进行创建
        if r.get(username) == None:
            r.set(username, 0)

        #  如果是第一次密码错误,开始计时
        if int(r.get(username)) == 0:
            r.expire(username, 200)
            # 累加
            r.incrby(username, 1)
            return Response({"msg": "您输入的用户名或密码错误", 'code': 400})

        else:
            # 在五分钟错误五次 进行封禁
            if int(r.get(username)) == 5:
                r.set(username + "black", str(password))
                # 封禁时间
                r.expire(username + "black", 1800)
                return Response({"msg": "您的账号被锁定30分钟", 'code': 400})
            # 进行累加
            r.incrby(username, 1)
            return Response({"msg": "用户名或密码错误", 'code': 400, })


# 用户管理页面-增删改查
class UserView(APIView):
    # 注册 --  增 post
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        try:
            user = UserModel(username=username, password=password)
            user.save()
            return Response({'code': 200, 'msg': '用户增加成功'})
        except Exception as e:
            print(str(e))
            return Response({'code': 405, 'msg': 'Sorry，用户已存在'})

    # 删除用户 - delete
    def delete(self, request):
        id = request.GET.get('id')
        UserModel.objects.filter(id=id).delete()
        return Response({'msg': '成功删除用户', 'code': 200})

    # 修改用户信息 - put
    def put(self, request):
        id = request.query_params.get('id')
        print(id)
        username = request.data.get('username')
        print(username)
        password = request.data.get('password')
        print(password)
        UserModel.objects.filter(id=id).update(username=username, password=password)
        return Response({'msg': '成功修改用户信息', 'code': 200})

    # 查找用户信息 - get
    def get(self, request):
        queryset = UserModel.objects.all()
        ser = UserSer(queryset, many=True)
        return Response({'data': ser.data, 'msg': '查询所有用户成功', 'code': 200})


# 用户管理页面-根据用户名查找用户
class ShowUserView(APIView):
    def get(self, request):
        # 根据名字查找
        username = request.GET.get('username')
        queryset = UserModel.objects.filter(username=username)
        ser = UserSer1(queryset, many=True)
        return Response(ser.data)


# 用户详情
class DetailUserView(APIView):
    # 查看所有用户
    def get(self, request):
        queryset = UserModel.objects.all()
        ser = UserSer1(queryset, many=True)
        return Response({'data': ser.data, 'msg': '查询所有用户成功', 'code': 200})

    # 更改用户名和密码
    # def put(self, request):
    #     username = request.GET.get('username')
    #     new_user = request.data.get('new_user', username)
    #     print(username, new_user)
    #     return Response(detail_updateuser(username, new_user))


# r = RedisQueue('queue')


# 修改用户名
class UpdateUserView(APIView):
    def put(self, request):
        # 获取id
        id = request.GET.get('id', None)
        # 用户名
        new_user = request.data.get('new_user', None)
        # 用户等级
        user_level = request.data.get('user_level', None)
        # 入队
        r.put(f'{id, new_user, user_level}')
        # r.order()
        return Response({'msg': '正在审核中，请耐心等待'})


# 修改用户名后获取结果
class GetJob(APIView):
    def get(self, request):
        # 出队
        id = request.query_params.get('id')
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        res = loop.run_until_complete(dojob())
        loop.close()
        a = r.hget('lz', id)
        print(a)
        if a.decode() == '200':
            return Response({"msg": '修改成功'})
        else:
            return Response({'msg': '用户名重复'})
            # 判断修改的用户名和数据库的用户名是否重复


authority = 1


# 返回中间件
class MiddleView(APIView):
    # 获取
    def get(self, request):
        return Response({'middle': authority == request.level})

    def put(self, request):
        global authority
        authority = int(not authority)
        return Response({'msg': '修改成功'})


# 三方登录导包
import time
import hmac
import base64
from hashlib import sha256
import urllib
import json
import requests


# 钉钉三方登录
def ding_back(request):
    appid = 'dingoar91fvryq6pugb1nx'
    redirect_uri = 'http://127.0.0.1:8000/z/ding_back/'
    # 获取code
    code = request.GET.get("code")
    t = time.time()
    # 时间戳
    timestamp = str((int(round(t * 1000))))
    # 密钥
    appSecret = 'Njh7SJwIE-MOoZa9P7nxgFf18iNOzCS2KvUaBybQ1xjTszXRA96XDvrTgttDHhVf'
    # 构造签名
    signature = base64.b64encode(
        hmac.new(appSecret.encode('utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
    # 请求接口，换取钉钉用户名
    payload = {'tmp_auth_code': code}
    headers = {'Content-Type': 'application/json'}
    # 导requests
    import requests
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature=' + urllib.parse.quote(
        signature.decode("utf-8")) + "&timestamp=" + timestamp + "&accessKey=dingoar91fvryq6pugb1nx",
                        data=json.dumps(payload), headers=headers)

    re_dict = json.loads(res.text)
    print(re_dict)
    # 判断是否为第一次登录
    user = UserModel.objects.filter(username=str("dingding_" + re_dict['user_info']['nick'])).first()

    sina_id = ''
    user_id = ''

    if user:
        # 代表曾经用过钉钉登录
        sina_id = user.username
        user_id = user.id
    else:
        # 代表首次登录，入库
        user = UserModel(username=str("dingding_" + re_dict['user_info']['nick']), password='')
        # 保存入库
        user.save()
        sina_id = str(re_dict.get('user_info'))
        # 查询用户id
        user = UserModel.objects.filter(username=str("dingding_" + re_dict['user_info']['nick'])).first()
        user_id = user.id

    # 进行跳转
    return redirect("http://127.0.0.1:8080/myback?sina_id=" + str(sina_id) + "&uid=" + str(user_id))


# 码云三方登录
class Gitee(View):
    def get(self, request):
        return redirect(
            "https://gitee.com/oauth/authorize?client_id=7f611851ce2cbd381390632e50e10ab00108a207dcc00d6c8de686a40fd7cd15&redirect_uri=http://127.0.0.1:8000/z/git_back/&response_type=code")


class GiteeBack(View):
    def get(self, request):
        code = request.GET.get("code", None)
        r = requests.post(
            "https://gitee.com/oauth/token?grant_type=authorization_code&code=%s&client_id=7f611851ce2cbd381390632e50e10ab00108a207dcc00d6c8de686a40fd7cd15&redirect_uri=http://127.0.0.1:8000/z/git_back/&client_secret=ec39df1740d798ac832ab3df1ac99aedd04459c6b7d552f43099ef24273554cc" % code)
        print(r.text)
        r = requests.get("https://gitee.com/api/v5/user?access_token=2b8c4824659611c8a920631bb5684008")

        print(r.text)
        name = json.loads(r.text)['name']
        user = UserModel.objects.filter(username=name)
        if user:
            return redirect('http://127.0.0.1:8080/myback')
        else:
            user = UserModel(username=str("gitee_" + name))
            user.save()
            user = UserModel.objects.filter(username=name)
            return redirect('http://127.0.0.1:8080/myback')


# 工单分类
# 递归
def xTree(datas):
    lists = []
    tree = {}
    parent_id = ''
    for i in datas:
        item = i
        tree[item['id']] = item
    root = None
    for i in datas:
        obj = i
        if not obj['pid']:
            root = tree[obj['id']]
            lists.append(root)
        else:
            parent_id = obj['pid']
            if 'childlist' not in tree[parent_id]:
                tree[parent_id]['childlist'] = []
            tree[parent_id]['childlist'].append(tree[obj['id']])
    return lists


class WorkOrderView(APIView):
    # 添加工单分类信息
    def post(self, request):
        name = request.data.get('name')
        pid = request.data.get('pid')
        if pid:
            WorkOrderModel.objects.create(name=name, pid=pid)
        else:
            WorkOrderModel.objects.create(name=name)
        return Response({'msg': '添加成功'})

    def get(self, request):
        # 获取工单列表
        workorder_list = WorkOrderModel.objects.all()
        # 序列化
        workorder_ser = WorkOrderSer(workorder_list, many=True)
        z_list = xTree(workorder_ser.data)
        return Response(z_list)


class Small_WorkOrderView(APIView):
    def get(self, request):
        # 获取工单列表
        workorder_list = WorkOrderModel.objects.all()
        # 序列化
        workorder_ser = WorkOrderSer(workorder_list, many=True)
        return Response(workorder_ser.data)


# MongoDB
# from pymongo import MongoClient
from z_Userapp.MyMongoDB import MyMonge

# 连接MongoDB
client = MyMonge('z_Cate', 'CateTemplate', **{'host': '127.0.0.1', 'port': 27017})


# 获取MongoDB数据
class GetMongo(APIView):
    def get(self, request):
        # 进入数据库
        # db = client.z_Cate
        # 集合
        # zst = db.CateTemplate
        id = request.GET.get('id', None)
        wid = WorkOrderModel.objects.filter(id=id).first()
        if wid.pid == 0:
            data = client.find({'wid': str(wid.id)})
        else:
            data = client.find({'wid': str(wid.pid)})
        return Response(eval(data['name']))


# 工单分类提交和展示详情视图
class StorageView(APIView):
    # 工单分类提交
    def post(self, request):
        # 获取wid
        wid = request.data.get('id')
        # 获取user_id
        user_id = request.data.get('user_id')
        # 获取工单名 类型转换
        name = request.data.get('name')
        # 获取审核人列表
        checklist = request.data.get('checklist')
        print(checklist)
        qnimg = request.data.get('qnimg')
        # 设置审核人为第一个数据
        now_check = checklist[0]
        work = WorkOrderModel.objects.filter(id=wid).first()  # 获取工单分类名
        xx_name = f'你收到了一条需要审核的{work.name}工单'  # 消息盒子的内容

        storage = StorageModel.objects.create(uid_id=user_id, wid_id=wid, message=name, checklist=str(checklist),
                                              start=1, now_check=str(now_check), qnimg=qnimg)
        if type(now_check) == list:
            for i in now_check:
                NestedList.objects.create(sid_id=storage.id, uid=i)
                # 添加到消息盒子

                r.hset(f'user{i}', f'message{storage.id}',
                       str({"name": xx_name, "wid": wid, "uid": i, "read": 0, "withdraw": 0}))
                # MessageModel.objects.create(name=xx_name, wid_id=wid, uid_id=i)
        else:
            NestedList.objects.create(sid_id=storage.id, uid=now_check)
            r.hset('user%s' % now_check, 'message%s' % storage.id,
                   str({"name": xx_name, "wid": wid, "uid": now_check, "read": 0, "withdraw": 0}))
            # MessageModel.objects.create(name=xx_name, wid_id=wid, uid_id=now_check)
        return Response({'msg': '添加成功', 'code': 200})

        # for index, i in enumerate(checklist):
        #     user = UserModel.objects.filter(id=i).first()
        #     name[f'审核人{index + 1}'] = user.username
        # name = str(name)
        # checklist = str(checklist)
        # print(user_id)
        # print(name)
        # 过滤查询
        # StorageList = StorageModel.objects.filter(uid=user_id, wid=wid).first()
        # 如果存在则修改工单
        # if StorageList:
        #     StorageModel.objects.filter(uid=user_id, wid=wid).update(uid=user_id, wid=wid, message=name,checklist=checklist, now_check=now_check, start=1,qnimg=qnimg)
        # # 不存在则创建一个工单
        # else:
        #     StorageModel.objects.create(uid_id=user_id, wid_id=wid, message=name, checklist=checklist,
        #                                 now_check=now_check, start=1,qnimg=qnimg)
        # # 返回成功信息
        # return Response({'msg': '恭喜您，成功提交', 'code': 200})

    # 工单详情展示
    def get(self, request):
        # 获取用户id
        user_id = request.GET.get('user_id')
        # 获取查询集
        storagelist = StorageModel.objects.filter(uid_id=user_id)
        # print(storagelist)
        # 定义一个空列表，用来存放查询集里面的数据
        k_list = []
        # 循环查询集
        for i in storagelist:
            print(i.message)
            # 定义一个字典
            data = {}
            # 字典里存放工单数据 并强转其类型
            data['message'] = eval(i.message)
            data['start'] = i.start

            if type(eval(i.now_check)) == list:
                now_check = eval(i.checklist).index(eval(i.now_check))
            else:
                now_check = eval(i.checklist).index(int(i.now_check))

            # now_check=eval(i.checklist).index(int(i.now_check))

            data['index'] = now_check
            data['qnimg'] = i.qnimg
            datalist = []
            for index, i in enumerate(eval(i.checklist)):
                datalist1 = []
                if type(i) == list:
                    for j in i:
                        user = UserModel.objects.filter(id=j).first()
                        datalist1.append(user.username)
                    datalist1 = ','.join(datalist1)
                    datalist.append(datalist1)
                else:
                    user = UserModel.objects.filter(id=i).first()
                    datalist.append(user.username)
                data['checklist'] = datalist

                # user = UserModel.objects.filter(id=i).first()
            # 把数据添加到 k_list
            k_list.append(data)
        # 返回列表
        return Response(k_list)


# 审核视图
class CheckView(APIView):
    # 审核
    def post(self, request):
        # 获取uid
        # uid = request.GET.get('uid')
        # 获取审核状态
        start = int(request.data.get('start'))
        # 获取id
        id = request.GET.get('id')
        return SimpleFactory.PlantExecute(start, id)
        # 判断，如果审核状态为2（2--通过）
        # if start == 2:
        #     # 过滤工单表 取第一条审核数据
        #     storage = StorageModel.objects.filter(now_check=uid, id=id, start=1).first()
        #     # 把取出来的审核人列表进行强转
        #     storage1 = eval(storage.checklist)
        #     # 并获取其下标
        #     index = storage1.index(int(uid))
        #     # 得到审核人列表长度
        #     length = len(eval(storage.checklist))
        #     # 如果审核人列表长度等于下标+1的话
        #     if length == index + 1:
        #         # 修改当前审核人的审核状态为审核已通过
        #         StorageModel.objects.filter(now_check=uid, id=id).update(start=2)
        #     else:
        #         StorageModel.objects.filter(now_check=uid, id=id).update(now_check=storage1[index + 1])
        #     return Response({'msg': '审核通过', 'code': 200})
        #
        # if start == 3:
        #     storage = StorageModel.objects.filter(now_check=uid, id=id, start=1).first()
        #     storage1 = eval(storage.checklist)
        #     index = storage1.index(int(uid))
        #     if index == 0:
        #         StorageModel.objects.filter(now_check=uid, id=id).update(start=3)
        #     else:
        #         StorageModel.objects.filter(now_check=uid, id=id).update(start=3, now_check=storage1[index - 1])
        #     return Response({'msg': '审核未通过', 'code': 400})
        # return Response({})

    # 获取当前审核人信息
    def get(self, request):
        uid = int(request.GET.get('uid'))
        nest = NestedList.objects.filter(uid=uid)
        storage_list = []
        for i in nest:
            work = StorageModel.objects.filter(id=i.sid_id).first()
            data = {}
            data['id'] = work.id
            data['message'] = eval(work.message)
            storage_list.append(data)
        print(storage_list)
        MessageModel.objects.filter(uid=uid, read=0).update(read=1)
        return Response(storage_list)


# 消息盒子视图
class MessageView(APIView):
    # 获取信息
    def get(self, request):
        uid = request.GET.get('uid')
        list1 = r.hgetall('user%s' % uid)
        # print(list1)
        message_list = []
        length = 0
        for key, values in list1.items():
            i = eval(values)
            message_list.append(i)
            if i['read'] == 0:
                length += 1
        return Response({'message': message_list, 'count': length})
        # return Response({})

    def put(self, request):
        wid = request.GET.get('id')
        uid = request.data.get('uid')
        c = r.hgetall('user%s' % uid)
        print(c)
        for key, values in c.items():
            print(key)
            i = eval(values)
            print(i)
            if wid == i['wid']:
                r.hset('user%s' % uid, key, str({"name": i['name'], "wid": wid, "uid": uid, "read": 1, "withdraw": 0}))
        return Response({})
        # uid = request.GET.get('uid')
        # print(uid)
        # message = MessageModel.objects.filter(uid_id=uid, read=0)
        # print(len(message))
        # return Response({'count': len(message)})


# 添加聊天消息
class ChatView(APIView):
    def post(self, request):
        send = request.data.get('send')
        name = request.data.get('name')
        img = request.data.get('img', None)
        print(send)
        print(name)
        print(img)
        ChatModel.objects.create(send=send, name=name, img=img)
        ran = ''.join(random.sample(string.digits, 4))
        r = redis.Redis()
        news = send + ran
        # 保存数据到redis
        r.hmset(news, {'uid': send, 'name': name})
        # 保存随机数到redis
        r.sadd(send, ran)
        # 过期删除数据库120s
        r.expire(ran, 120)
        return Response({'msg': '消息保存成功'})

    # 保存消息
    # def post(self, request):
    #     # 获取
    #     send = request.data.get('send')
    #     reception = request.data.get('reception')
    #     name = request.data.get('name')
    #     img = request.data.get('img', None)
    #     # 连接redis
    #     r = redis.Redis()
    #     # 保存到数据库
    #     try:
    #         chat = ChatModel(send=send, reception=reception, name=name, img=img)
    #         chat.save()
    #         # 生成三位随机数，防止保存其他数据时把上面的数据顶替掉
    #         ran = ''.join(random.sample(string.digits, 3))
    #         news = ran + send
    #         # 保存到redis
    #         r.hmset(news, {'send': send, 'reception': reception, 'name': name, 'img': img})
    #         r.zadd(ran, send)
    #         r.expire(news, 120)
    #         r.expire(ran, 120)
    #         return Response({'msg': '消息保存成功', 'code': 200})
    #     # 异常处理
    #     except Exception as e:
    #         print(e)
    #         return Response({'msg': '消息保存失败', 'code': 400})

    # 查询全部消息
    def get(self, request):
        # 获取查询集进行排序
        queryset = ChatModel.objects.all().order_by()
        ser = ChatSer(queryset, many=True)
        return Response(ser.data)

    # 撤回消息
    def put(self, request):
        id = request.data.get('id')
        uid = request.data.get('uid')
        r = redis.Redis()
        rand = r.smembers(uid)
        print(rand)
        # 查询id所对应的消息
        chat = ChatModel.objects.get(id=id)
        # 循环随机数
        for i in rand:
            i = i.decode()
            # 查看数据库名是否存在
            print(r.hgetall(str(uid) + str(i)))
            if r.hgetall(str(uid) + str(i)):
                # 修改撤销状态
                chat.withdraw = 1
                chat.save()
                return Response({'msg': '撤销成功'})
            return Response({'msg': '撤回失败，超过两分钟了'})


# 七牛云token
from qiniu import Auth


def qiniu_token():
    qn = Auth('vkoJGPbnvO-zwjVX3DcVJnXtpt9gclvnH5N_A4he', 'Mab055XtHiEYRRoyLEn02JBsY2kRnDAsmonQdhiT')
    # 指定上传空间, 返回token值
    token = qn.upload_token('shixun-p8')
    return token


class UpTokenView(View):
    def get(self, request):
        """
        七牛云token接口
        """
        return JsonResponse({'token': qiniu_token()})


import upyun


# 定义文件上传类
class UploadFile(View):
    def post(self, request):
        file = request.FILES.get('file')
        print(file)
        up = upyun.UpYun('shixun-p8', username='coisnini', password='5LQiEB6YUY4aTIHQDNLMPpVf2QpnNeft')
        headers = {'x-gmkerl-rotate': '180'}
        for chunk in file.chunks():
            res = up.put('/touxiang1.jpg', chunk, checksum=True, headers=headers)
        # 返回结果
        return HttpResponse(json.dumps({'filename': file.name}), content_type='application/json')


# 导入websocket装饰器
from dwebsocket.decorators import accept_websocket


# 接收前端信息
@accept_websocket  # 装饰器
def test_socket(request):  # FBV
    if request.is_websocket():
        for message in request.websocket:
            c = str(message, encoding='utf-8')
            print(c)
            request.websocket.send(message)


# 主动推送消息
@accept_websocket
def test_websocket(request):
    if request.is_websocket():
        while 1:
            time.sleep(1)  ## 向前端发送时间
            dit = {
                'time': time.strftime('%Y.%m.%d %H:%M:%S', time.localtime(time.time()))
            }
            request.websocket.send(json.dumps(dit))


@accept_websocket
def service(request, reception, send):
    if request.is_websocket():
        while 1:
            # time.sleep(1)
            list1 = []
            list2 = []
            time.sleep(1)
            list1.append(send)
            list1.append(reception)
            list1.sort()
            key = str(list1)
            data = r.lrange(key, 0, -1)

            for j in data:
                user = UserModel.objects.filter(id=reception).first()
                _ = {}
                j = eval(j)
                _['send'] = j['uid']
                _['name'] = j["name"]
                _['reception'] = j["reception"]
                _['withdraw'] = j["withdraw"]
                _['read'] = j["read"]
                _['date'] = j["date"]
                _['uname'] = user.username
                list2.append(_)
                list2 = sorted(list2, key=lambda x: x['date'])
            request.websocket.send(json.dumps(list2))


class AddMessageView(APIView):
    def post(self, request):
        send = request.data.get('send')  # 发送人
        reception = request.data.get('reception')  # 接收人
        name = request.data.get('name')
        list1 = []
        list1.append(str(send))
        list1.append(str(reception))
        list1.sort()
        key = str(list1)
        info = str({'uid': send, 'name': name, 'reception': reception, 'withdraw': 0, 'read': 0, 'date': time.time()})
        r.lpush(key, info)
        return Response({'msg': '发送成功'})
